package com.hlkj.warboot.module_sys.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hlkj.warboot.configurer.security.SecurityUser;
import com.hlkj.warboot.configurer.util.*;
import com.hlkj.warboot.configurer.util.DateUtil;
import com.hlkj.warboot.configurer.util.base.BaseExceptionUtil;
import com.hlkj.warboot.configurer.util.enums.DictionaryEnum;
import com.hlkj.warboot.configurer.util.enums.OperateEnum;
import com.hlkj.warboot.module_sys.entity.AdminEntity;
import com.hlkj.warboot.module_sys.entity.MailEntity;
import com.hlkj.warboot.module_sys.entity.PermissionEntity;
import com.hlkj.warboot.module_sys.entity.RoleEntity;
import com.hlkj.warboot.module_sys.entity.wrapper.AdminWrapper;
import com.hlkj.warboot.module_sys.mapper.AdminMapper;
import com.hlkj.warboot.module_sys.mapper.RoleMapper;
import com.hlkj.warboot.module_sys.service.AdminService;
import com.hlkj.warboot.module_sys.service.MailService;
import com.hlkj.warboot.module_sys.service.PermissionService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.text.MessageFormat;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 系统管理员 前端控制器
 * </p>
 *
 * @author lixing_java@163.com
 * @since 2020-06-11
 */
@Controller
@RequestMapping("/sys/admin")
public class AdminControler {
    @Resource
    private AdminMapper adminMapper;

    @Resource
    private AdminService adminService;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private PermissionService permissionService;

    @Resource
    private MailService mailService;

    /*
     * @Description TODO 图片验证码
     * @Author 李星
     * @Date 2019/3/10 15:38
     * @Param [request, response]
     * @return void
     */
    @RequestMapping("verifyCode")
    public void verifyCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");

        // 生成随机验证码
        String verifyCode = StrUtil.genRandomStr("mix",4).toLowerCase();
        // 存入session对象
        request.getSession().setAttribute(OperateEnum.VERIFYCODE.getValue(), verifyCode.toLowerCase());

        // 生成验证码图片并响应到页面
        ServletOutputStream servletOutputStream = null;
        try {
            servletOutputStream = response.getOutputStream();
            VerifyCodeUtil.outputImage_2(verifyCode, 110, 38, servletOutputStream);
        } catch (IOException e) {
            LoggerUtil.error(MessageFormat.format("输出验证码出错：{0}", e.getMessage()));
        } finally {
            if (servletOutputStream != null) {
                try {
                    servletOutputStream.close();
                } catch (IOException e) {
                    LoggerUtil.info("获取验证码模块-关闭ServletOutputStream对象出错：" + e);
                }
            }
        }
    }

    /*
     * @Description TODO 跳转到登陆页面
     * @Author 李星
     * @Date 2019/6/2 9:04
     * @Param [request]
     * @return java.lang.String
     */
    @GetMapping("toLogin")
    public String toLogin() {
        return "sys/admin/login";
    }

    /*
     * @Description TODO 跳转到注册页面
     * @Author 李星
     * @Date 2019/6/2 9:04
     * @Param []
     * @return java.lang.String
     */
    @GetMapping("toRegister")
    public String toRegister() {
        return "sys/admin/register";
    }

    /*
     * @Description TODO 注册
     * @Author 李星
     * @Date 2019/2/16 13:07
     * @Param [user]
     * @return java.lang.Object
     */
    @PostMapping("register")
    @ResponseBody
    public Object register(HttpServletRequest request, AdminEntity entity) throws Exception {
        // 校验验证码
        HttpSession session = request.getSession();
        Object verifyCode = request.getAttribute(OperateEnum.VERIFYCODE_IMG.getValue());
        if (verifyCode == null) {
            return ResponseUtil.fail("请重新填写验证码");
        }
        if (!verifyCode.toString().equalsIgnoreCase(entity.getBaseVerifyCodeImg())) {
            session.removeAttribute(OperateEnum.VERIFYCODE_IMG.getValue());
            return ResponseUtil.fail("验证码输入错误");
        }
        session.removeAttribute(OperateEnum.VERIFYCODE_IMG.getValue());

        // 判断账号是否被注册
        QueryWrapper<AdminEntity> adminEntityQueryWrapper = new QueryWrapper<AdminEntity>();
        adminEntityQueryWrapper.eq("account", entity.getAccount());
        int count = adminService.count(adminEntityQueryWrapper);
        if (count > 0) {
            return ResponseUtil.fail("该账号已被注册");
        }

        // RSA 私钥解密
        // String pass = RSAUtil.decryptByPrivateKey(rsaProperties.getPrivateKey(), entity.getPass());

        // 注册
        entity.setActive(1); // 激活
        entity.setGrade(2); // 普通管理员
        entity.setAge(DateUtil.betweenTwoDate(entity.getBirthday(),new Date(), ChronoUnit.YEARS)); // age由birthday转化而来
        boolean flag = adminService.save(entity);

        LoggerUtil.info("注册结果：" + flag);
        return ResponseUtil.success(flag);
    }

    /*
     * @Description TODO 系统后台入口
     * @Author 李星
     * @Date 2019/9/28 12:46
     * @Param [authentication 认证成功后的Authentication对象]
     * @return org.springframework.web.servlet.ModelAndView
     */
    @GetMapping("index")
    public ModelAndView index(Authentication authentication) throws Exception {
        // 获取认证后的用户信息
        SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();

        // 查询用户的菜单权限信息
        List<PermissionEntity> permissionEntityList;
        if (securityUser.getGrade() == 1) { // TODO 超级管理员
            QueryWrapper<PermissionEntity> permissionEntityQueryWrapper = new QueryWrapper<PermissionEntity>();
            permissionEntityQueryWrapper.eq("category",1);
            permissionEntityQueryWrapper.orderByAsc("sort");
            permissionEntityList = permissionService.list(permissionEntityQueryWrapper);
        } else { // TODO 非超级管理员
            AdminEntity adminEntity = new AdminEntity();
            adminEntity.setAccount(securityUser.getUsername());
            adminEntity = adminMapper.queryPermissionForMenu(adminEntity);
            permissionEntityList = adminEntity.getPermissionPojoList();
        }

        ModelAndView modelAndView = new ModelAndView("sys/index");
        modelAndView.addObject("permissionList", permissionEntityList );
        return modelAndView;
    }

    /*
     * @Description TODO 主页
     * @Author 李星
     * @Date 2019/4/21 13:11
     * @Param []
     * @return org.springframework.web.servlet.ModelAndView
     */
    @GetMapping("welcome")
    public ModelAndView welcome() {
        return new ModelAndView("sys/welcome");
    }

    /*
     * @Description TODO 跳转到忘记密码页面
     * @Author 李星
     * @Date 2019/6/2 9:04
     * @Param []
     * @return java.lang.String
     */
    @GetMapping("toForgetPass")
    public String toForgetPass() {
        return "sys/admin/forgetPass";
    }

    /*
     * @Description TODO 修改密码
     * @Author 李星
     * @Date 2019/3/18 21:23
     * @Param [entity]
     * @return java.lang.Object
     */
    @PostMapping("modifyPass")
    @ResponseBody
    public Object modifyPass(AdminEntity entity) {
        // 根据当前管理员账号查询其邮件信息，校验用户输入的邮件验证码是否合法
        QueryWrapper<MailEntity> mailEntityQueryWrapper = new QueryWrapper<>();
        mailEntityQueryWrapper.eq("create_user_account", entity.getAccount());
        mailEntityQueryWrapper.eq("category",DictionaryEnum.MAIL_FORGET_PASSWORD.getValue());
        mailEntityQueryWrapper.likeLeft("text", entity.getBaseVerifyCodeMail());
        List<MailEntity> mailEntityList = mailService.list(mailEntityQueryWrapper);
        if (mailEntityList.isEmpty()) {
            return ResponseUtil.fail("邮箱验证码错误");
        }

        // 修改密码
        UpdateWrapper<AdminEntity> adminEntityUpdateWrapper = new UpdateWrapper<AdminEntity>();
        adminEntityUpdateWrapper.eq("account", entity.getAccount());
        boolean flag = adminService.update(entity, adminEntityUpdateWrapper);

        if (flag) {
            return ResponseUtil.success();
        } else {
            return ResponseUtil.fail("密码修改失败");
        }
    }

    /*
     * @Description TODO 跳转到个人信息页面
     * @Author 李星
     * @Date 2019/9/28 12:48
     * @Param [authentication, category]
     * @return org.springframework.web.servlet.ModelAndView
     */
    @GetMapping("toUserInfo/{category}")
    public ModelAndView toUserInfo(Authentication authentication, @PathVariable String category) throws Exception {
        ModelAndView modelAndView = new ModelAndView();

        // 获取认证成功后的用户信息
        SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();

        QueryWrapper<AdminEntity> adminEntityQueryWrapper = new QueryWrapper<AdminEntity>();
        adminEntityQueryWrapper.eq("account", securityUser.getUsername());
        AdminEntity adminEntity = adminService.getOne(adminEntityQueryWrapper);
        modelAndView.addObject("entity",adminEntity);

        if ("base".equals(category)) {
            modelAndView.setViewName("sys/admin/userInfo");
        } else if ("pwd".equals(category)) {
            modelAndView.setViewName("sys/admin/userPwd");
        } else {
            throw new BaseExceptionUtil("您访问的页面不存在");
        }
        return modelAndView;
    }

    /*
     * @Description TODO 更新个人信息
     * @Author 李星
     * @Date 2019/6/2 9:04
     * @Param []
     * @return java.lang.String
     */
    @PostMapping("updateUserInfo")
    @ResponseBody
    public JSONObject updateUserInfo(AdminEntity entity) throws Exception {
        boolean flag = adminService.updateById(entity);
        if (flag) {
            return ResponseUtil.success();
        } else {
            return ResponseUtil.fail("更新个人信息失败");
        }
    }

    /*
     * @Description TODO 跳转导上传头像界面
     * @Author 李星
     * @Date 2019/10/13 15:05
     * @Param []
     * @return java.lang.String
     */
    @GetMapping("toUpdateCover")
    public String toUpdateCover() throws Exception {
        return "sys/admin/updateCover";
    }

    /*
     * @Description TODO 分页
     * @Author 李星
     * @Date 2019/2/16 13:08
     * @Param []
     * @return org.springframework.web.servlet.ModelAndView
     */
    @GetMapping("toPage")
    public ModelAndView toPage() throws Exception {
        return new ModelAndView( "sys/admin/userList" );
    }
    @PostMapping("page")
    @ResponseBody
    public Object page(AdminEntity entity) throws Exception {
        LoggerUtil.info(MessageFormat.format("【管理员分页】条件：{0}", JSON.toJSONString(entity)));

        IPage<AdminEntity> iPage = adminService.page(new Page<>(entity.basePageNum,entity.basePageSize), AdminWrapper.queryWrapper(entity));

        LoggerUtil.info(MessageFormat.format("【管理员分页】结果：{0}", iPage.getSize()));
        return  ResponseUtil.success(iPage);
    }

    /*
     * @Description TODO 跳转到添加|编辑页面
     * @Author 李星
     * @Date 2019/9/10 13:57
     * @Param [authentication, category, id]
     * @return org.springframework.web.servlet.ModelAndView
     */
    @GetMapping("toModify/{id}")
    public ModelAndView toModify(Authentication authentication, @PathVariable String id) throws Exception {
        ModelAndView modelAndView = new ModelAndView();

        SecurityUser securityUser = (SecurityUser)authentication.getPrincipal();
        modelAndView.addObject("adminGrade", securityUser.getGrade());

        if ("null".equals(id)) {
            modelAndView.setViewName("sys/admin/userAdd");
        } else {
            modelAndView.setViewName("sys/admin/userUpdate");
            AdminEntity adminEntity = adminService.getById(id); // 根据主键查询用户信息
            modelAndView.addObject("entity", adminEntity);
        }

        return modelAndView;
    }

    /*
     * @Description TODO 保存编辑
     * @Author 李星
     * @Date 2019/9/10 16:12
     * @Param [entity]
     * @return java.lang.Object
     */
    @PostMapping("saveModify/{category}")
    @ResponseBody
    public Object saveModify(AdminEntity entity,@PathVariable String category) throws Exception {
        boolean flag;
        if ("insert".equals(category)) {
            flag = adminService.save(entity);
        } else if ("update".equals(category)) {
            flag = adminService.updateById(entity);
        } else {
            throw new BaseExceptionUtil("用户保存时获取参数失败");
        }
        if (flag) {
            return ResponseUtil.success();
        } else {
            return ResponseUtil.fail("操作失败");
        }
    }

    /*
     * @Description TODO 删除
     * @Author 李星
     * @Date 2019/9/11 9:14
     * @Param [entity]
     * @return java.lang.Object
     */
    @PostMapping("delete")
    @ResponseBody
    public Object delete(AdminEntity entity) throws Exception {
        LoggerUtil.info(MessageFormat.format("【删除管理员】条件：{0}", entity.getId()));

        boolean flag;
        if (StrUtil.isEffective(entity.getId())) {
            if (entity.getId().contains(",")) {
                flag = adminService.removeByIds(Arrays.asList(entity.getId().split(",")));
            } else {
                flag = adminService.removeById(entity.getId());
            }
            LoggerUtil.info(MessageFormat.format("【删除管理员】结果：{0}", flag));
            return ResponseUtil.success(flag);
        } else {
            return ResponseUtil.fail("主键缺失");
        }
    }

    /*
     * @Description TODO 跳转到授权页面
     * @Author 李星
     * @Date 2019/9/12 16:34
     * @Param [id 用户编号]
     * @return java.lang.Object
     */
    @RequestMapping("toAuthorization/{id}")
    public Object toAuthorization(@PathVariable String id) throws Exception {
        ModelAndView modelAndView = new ModelAndView("sys/admin/userAuthorization");
        modelAndView.addObject("adminId", id);

        RoleEntity roleEntity = new RoleEntity();
        roleEntity.setActive(1); // 角色状态（1:有效,2:禁用）
        roleEntity.setBaseAdminId(id); // 当前需要授权的管理员id
        List<RoleEntity> roleEntityList = roleMapper.selectCasUser(roleEntity);

        modelAndView.addObject("roleList", roleEntityList);
        return modelAndView;
    }

    /*
     * @Description TODO 授权
     * @Author 李星
     * @Date 2019/9/12 16:34
     * @Param [id]
     * @return java.lang.Object
     */
    @RequestMapping("authorization")
    @ResponseBody
    public Object authorization(AdminEntity entity) throws Exception {
        LoggerUtil.info(MessageFormat.format("【管理员授权】条件：{0}", JSONObject.toJSONString(entity)));

        int deleteResult = adminMapper.deleteAdminRole(entity);
        LoggerUtil.info(MessageFormat.format("【清空管理员（{0}）的所有角色】结果：{1}", entity.getId(), deleteResult));

        if (StrUtil.isEffective(entity.getBaseAdminRoleId())) {
            entity.setBaseList(Arrays.asList(entity.getBaseAdminRoleId().split(","))); // 角色编号集合
            entity.setBaseAdminRoleId(null);
            int insertResult = adminMapper.insertAdminRole(entity); // 批量添加角色数据
            LoggerUtil.info(MessageFormat.format("【批量添加管理员（{0}）的角色】结果：{1}", entity.getBaseAdminRoleId(), insertResult));
        }

        return ResponseUtil.success();
    }

    /*
     * @Description TODO 导出Excel
     * @Author 李星
     * @Date 2019/2/16 16:46
     * @Param [pojo, response]
     * @return java.lang.Object
     */
    @PostMapping("export")
    public void export(HttpServletResponse response, AdminEntity entity) throws Exception {
        // 查询用户信息
        List<AdminEntity> exportData = adminService.list(AdminWrapper.queryWrapper(entity));

        // 全局导出参数
        String exportName = "管理员信息"; // 导出文件的名称
        int exportRows = exportData.size(); // 导出数据的条数
        int sheetPageSize = 10; // 默认每一个Sheet工作表最多存储65535行数据
        int headerLineHeight = 0; // 默认表头占据的行数为0（即不设置表头）
        int currentSheetIndex = 1; // 默认从第一个Sheet工作表开始执行写入
        int currentRowIndex; // 默认从Sheet工作表的第二行开始写入，第二行的索引为1

        // 创建工作簿
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        // 创建工作表
        Sheet sheet = workbook.createSheet("sheet" + currentSheetIndex);
        // 列自适应 sheet.createFreezePane( 2, 1 );

        // 创建数据格式对象
        DataFormat dataFormat = workbook.createDataFormat();
        // 标题列样式
        CellStyle cellStyle_title = ExcelPoiUtil.getCellStyle_title(workbook);
        // 文本格式的列样式
        CellStyle cellStyle_body_text = ExcelPoiUtil.getCellStyle_body_text(workbook, dataFormat);
        // 日期格式的列样式
        CellStyle cellStyle_body_datetime = ExcelPoiUtil.getCellStyle_body_datatime(workbook, dataFormat);

        // 创建标题行
        String[] titleCells = {"账号", "年龄", "性别", "手机号码", "注册时间"};
        int titleCellLen = titleCells.length;
        // 创建数据行
        int currentDataIndex; // 当前待导出数据的索引
        for (int rowNum = 0; rowNum <= exportRows; rowNum++) {
            // 为每个Sheet表空间的首行创建标题
            if (rowNum == 0 || (rowNum > sheetPageSize && rowNum % sheetPageSize == 1)) {
                if (rowNum == 0) {
                    ExcelPoiUtil.createTitleRow(sheet, headerLineHeight, cellStyle_title, titleCells, titleCellLen);
                    continue;
                } else {
                    currentSheetIndex += 1;
                    // 当表空间的索引大于1时，需要创建新的表空间
                    sheet = workbook.createSheet("sheet" + currentSheetIndex);
                    ExcelPoiUtil.createTitleRow(sheet, headerLineHeight, cellStyle_title, titleCells, titleCellLen);
                }
            }

            // 创建真实数据行，currentDataIndex数据索引从0开始，对应Row行号currentRowIndex从1开始
            currentDataIndex = rowNum - 1;
            currentRowIndex = currentDataIndex % sheetPageSize == 0 ? 1 : rowNum - ((currentSheetIndex - 1) * sheetPageSize);
            LoggerUtil.info("currentSheetIndex=" + currentSheetIndex + ",currentDataIndex=" + currentDataIndex + "，currentRowIndex=" + currentRowIndex);
            Row row = sheet.createRow(currentRowIndex + headerLineHeight);

            // 创建列
            for (int cellNum = 0; cellNum < titleCellLen; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellStyle(cellStyle_body_text);
                switch (cellNum) {
                    case 0:
                        String account = exportData.get(currentDataIndex).getAccount();
                        cell.setCellValue(StrUtil.isEffective(account) ? account : ""); // 账号
                        break;
                    case 1:
                        Integer age = exportData.get(currentDataIndex).getAge();
                        cell.setCellValue(age == null ? "" : age.toString()); // 年龄
                        break;
                    case 2:
                        Integer sex_ = exportData.get(currentDataIndex).getSex();
                        String sex;
                        if (DictionaryEnum.SEX_MALE.getValue()==sex_) {
                            sex = "男";
                        } else if (DictionaryEnum.SEX_FEMALE.getValue()==sex_) {
                            sex = "女";
                        } else {
                            sex = "未知";
                        }
                        cell.setCellValue(sex); // 性别
                        break;
                    case 3:
                        String phone = exportData.get(currentDataIndex).getPhone();
                        cell.setCellValue(StrUtil.isEffective(phone) ? phone : ""); // 手机号码
                        break;
                    case 4:
                        cell.setCellStyle(cellStyle_body_datetime);// 样式
                        Date createTime = exportData.get(currentDataIndex).getCreateTime();
                        cell.setCellValue(createTime == null ? "" : DateUtil.dateToDateTimeCharacter(createTime)); // 注册时间
                        break;
                }
            }
        }

        // 输出Excel文件到浏览器
        ResponseUtil.outputExcelFile(workbook, OperateEnum.EXCEL2003.getValue(), exportName, response);
    }
}

